package com.lonely.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.utils.JsonUtil;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.order.domain.dto.order.AddOrderLogDTO;
import com.lonely.order.domain.dto.split.SplitOrderDTO;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderSplit;
import com.lonely.order.domain.vo.split.GetSplitFactoryNameVO;
import com.lonely.order.enums.OrderSplitEnum;
import com.lonely.order.mapper.SysOrderSplitMapper;
import com.lonely.order.service.IOrderLogService;
import com.lonely.order.service.IOrderService;
import com.lonely.order.service.IOrderSplitService;
import com.lonely.product.service.IOrderPostFinishingService;
import com.lonely.product.service.IOrderSewingService;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.domain.entity.SysProductionLine;
import com.lonely.system.enums.SysFactoryEnum;
import com.lonely.system.service.ISysFactoryService;
import com.lonely.system.service.ISysProductionLineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 订单分单服务实现类
 *
 * @author fzzf
 */
@Service
public class OrderSplitServiceImpl extends ServiceImpl<SysOrderSplitMapper, SysOrderSplit> implements IOrderSplitService {

    @Autowired
    private IOrderService orderService;

    @Autowired
    private ISysFactoryService sysFactoryService;

    @Autowired
    private IOrderSewingService orderSewingService;

    @Autowired
    private IOrderPostFinishingService orderPostFinishingService;

    @Autowired
    private IOrderLogService orderLogService;

    @Autowired
    private ISysProductionLineService productionLineService;

    /**
     * 分单
     *
     * @param splitOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void splitOrders(SplitOrderDTO splitOrderDTO) {

        SysFactory sysFactory = this.sysFactoryService.getById(splitOrderDTO.getFactoryId());
        Assert.notNull(sysFactory, "工厂不存在");

        OrderSplitEnum.SplitTypeEnum typeEnum = OrderSplitEnum.SplitTypeEnum.getInstance(splitOrderDTO.getType());

        SysFactoryEnum.FactoryType factoryType = SysFactoryEnum.FactoryType.getInstance(sysFactory.getType());
        if (factoryType == SysFactoryEnum.FactoryType.OWN) {
            Assert.notNull(splitOrderDTO.getProductionLineId(), "生产线id不能为空");
        }
        if (factoryType == SysFactoryEnum.FactoryType.COOPERATIVE) {
            Assert.notNull(splitOrderDTO.getExpectedReturnTime(), "期望回货时间不能为空");
            Assert.notEmpty(splitOrderDTO.getPriceMultiple(), "工价倍率不能为空");
        }

        List<SysOrder> sysOrders = this.orderService.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, splitOrderDTO.getProduceOrderIds())
        );
        List<Long> orderIds = sysOrders.stream().map(BaseEntity::getId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }

        // 先删除指定订单id的该类型的分单记录
        super.remove(new LambdaQueryWrapper<SysOrderSplit>()
                .in(SysOrderSplit::getOrderId, orderIds)
                .eq(SysOrderSplit::getType, splitOrderDTO.getType())
        );

        // 添加新的分单记录
        List<SysOrderSplit> sysOrderSplits = sysOrders.stream().map(sysOrder -> {
            SysOrderSplit sysOrderSplit = new SysOrderSplit();
            sysOrderSplit.setOrderId(sysOrder.getId());
            sysOrderSplit.setProduceOrderId(sysOrder.getProduceOrderId());
            sysOrderSplit.setType(typeEnum.getType());
            sysOrderSplit.setFactoryId(splitOrderDTO.getFactoryId());
            sysOrderSplit.setProductionLineId(splitOrderDTO.getProductionLineId());
            sysOrderSplit.setExpectedReturnTime(splitOrderDTO.getExpectedReturnTime());
            sysOrderSplit.setPriceMultiple(splitOrderDTO.getPriceMultiple());
            sysOrderSplit.setCreateBy(SecurityUtils.getUserId());
            sysOrderSplit.setUpdateBy(SecurityUtils.getUserId());
            return sysOrderSplit;
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(sysOrderSplits)) {
            // 入库
            super.saveBatch(sysOrderSplits);

            // 分单后，判断是否存在待分单的车缝数据需要处理
            if (typeEnum == OrderSplitEnum.SplitTypeEnum.WORKSHOP) {
                List<Long> produceOrderIds = sysOrderSplits.stream().map(SysOrderSplit::getProduceOrderId).collect(Collectors.toList());
                this.orderSewingService.orderSplitAfterProcess(produceOrderIds, sysFactory);
            }

            if (typeEnum == OrderSplitEnum.SplitTypeEnum.TAIL) {
                // 尾部分单，处理后整数据
                List<Long> produceOrderIds = sysOrderSplits.stream().map(SysOrderSplit::getProduceOrderId).collect(Collectors.toList());
                this.orderPostFinishingService.orderTailSplitAfterProcess(produceOrderIds, sysFactory);
            }
        }


        // 更新订单的工厂权限
        Map<Long, List<Long>> orderFactoryIds = super.list(new LambdaQueryWrapper<SysOrderSplit>()
                .in(SysOrderSplit::getOrderId, orderIds)
                .eq(SysOrderSplit::getStatus, CommonStatus.ENABLE.code)
        ).stream().collect(Collectors.groupingBy(SysOrderSplit::getOrderId, Collectors.mapping(SysOrderSplit::getFactoryId, Collectors.toList())));
        for (SysOrder sysOrder : sysOrders) {
            // 查询该订单最新的分单记录
            List<Long> splitFactoryIds = Optional.ofNullable(orderFactoryIds.get(sysOrder.getFactoryId())).orElse(new ArrayList<>());
            List<Long> factoryPermission = Stream.concat(Stream.of(sysOrder.getFactoryId()), splitFactoryIds.stream()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            sysOrder.setFactoryPermission(JsonUtil.toJsonString(factoryPermission));
        }
        this.orderService.updateBatchById(sysOrders);

        // 添加操作日志
        List<AddOrderLogDTO> addOrderLogs = orderIds.stream().map(x -> {
            String splitName = StrUtil.EMPTY;
            if (typeEnum == OrderSplitEnum.SplitTypeEnum.WORKSHOP) {
                splitName = "车间";
            }
            if (typeEnum == OrderSplitEnum.SplitTypeEnum.TAIL) {
                splitName = "尾部";
            }
            String title = String.format("%s分单到%s", splitName, sysFactory.getName());
            return new AddOrderLogDTO(x, title);
        }).collect(Collectors.toList());
        this.orderLogService.batchAddOrderLog(addOrderLogs);
    }

    /**
     * 查询指定订单id对应分单工厂名称
     *
     * @param orderIds
     */
    @Override
    public Map<Long, GetSplitFactoryNameVO> getSplitFactoryNameByOrderIds(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new HashMap<>();
        }
        List<SysOrderSplit> orderSplitList = super.list(new LambdaQueryWrapper<SysOrderSplit>()
                .in(SysOrderSplit::getOrderId, orderIds)
                .eq(SysOrderSplit::getStatus, CommonStatus.ENABLE.code));

        // 订单分单映射
        Map<Long, List<SysOrderSplit>> orderSplitMap = orderSplitList.stream().collect(Collectors.groupingBy(SysOrderSplit::getOrderId));

        // 工厂id和工厂名称的映射
        List<Long> factoryIds = orderSplitList.stream().map(SysOrderSplit::getFactoryId).distinct().collect(Collectors.toList());
        Map<Long, String> factoryNameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(factoryIds)) {
            factoryNameMap.putAll(this.sysFactoryService.list(new LambdaQueryWrapper<SysFactory>().in(SysFactory::getId, factoryIds)).stream()
                    .collect(Collectors.toMap(BaseEntity::getId, SysFactory::getName)));
        }

        // 产线id和产线名称的映射
        List<Long> plIds = orderSplitList.stream().map(SysOrderSplit::getProductionLineId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Long, String> plNameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(plIds)) {
            plNameMap.putAll(this.productionLineService.list(new LambdaQueryWrapper<SysProductionLine>()
                    .in(SysProductionLine::getId, plIds)
            ).stream().collect(Collectors.toMap(BaseEntity::getId, SysProductionLine::getName, (x, y) -> x)));
        }

        Map<Long, GetSplitFactoryNameVO> result = new HashMap<>();
        orderSplitMap.forEach((orderId, sysOrderSplits) -> {
            GetSplitFactoryNameVO getSplitFactoryNameVO = new GetSplitFactoryNameVO();

            for (SysOrderSplit sysOrderSplit : sysOrderSplits) {
                if (Objects.equals(sysOrderSplit.getType(), OrderSplitEnum.SplitTypeEnum.WORKSHOP.getType())) {
                    getSplitFactoryNameVO.setWorkshopFactoryName(MapUtil.getStr(factoryNameMap, sysOrderSplit.getFactoryId()));

                    if (sysOrderSplit.getProductionLineId() != null) {
                        getSplitFactoryNameVO.setWorkshopProductionLineName(plNameMap.get(sysOrderSplit.getProductionLineId()));
                    }
                }
                if (Objects.equals(sysOrderSplit.getType(), OrderSplitEnum.SplitTypeEnum.TAIL.getType())) {
                    getSplitFactoryNameVO.setTailFactoryName(MapUtil.getStr(factoryNameMap, sysOrderSplit.getFactoryId()));

                    if (sysOrderSplit.getProductionLineId() != null) {
                        getSplitFactoryNameVO.setTailProductionLineName(plNameMap.get(sysOrderSplit.getProductionLineId()));
                    }
                }
            }
            result.put(orderId, getSplitFactoryNameVO);
        });

        return result;
    }

    /**
     * 获取车间分单信息
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public SysOrderSplit getWorkshopSplit(Long produceOrderId) {
        return super.getOne(new LambdaQueryWrapper<SysOrderSplit>()
                .eq(SysOrderSplit::getProduceOrderId, produceOrderId)
                .eq(SysOrderSplit::getType, OrderSplitEnum.SplitTypeEnum.WORKSHOP.getType())
                .eq(SysOrderSplit::getStatus, CommonStatus.ENABLE.code)
        );
    }

    /**
     * 获取尾部分单信息
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public SysOrderSplit getTailSplit(Long produceOrderId) {
        return super.getOne(new LambdaQueryWrapper<SysOrderSplit>()
                .eq(SysOrderSplit::getProduceOrderId, produceOrderId)
                .eq(SysOrderSplit::getType, OrderSplitEnum.SplitTypeEnum.TAIL.getType())
                .eq(SysOrderSplit::getStatus, CommonStatus.ENABLE.code)
        );
    }
}
